package account.common;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TelephoneNumber {

    private final Object data;

    private TelephoneNumber(String plainText) {
        data = plainText;
    }

    public String asPlainText() {
        if (data instanceof String plainText) {
            return plainText;
        }
        return "";
    }

    public static TelephoneNumber fromUncheckedInput(CharSequence input) throws TelephoneNumberParser.TextParserError {
        if (null == input) {
            // FIXME: 暂时还不确定应该何时抛出空指针异常
            return new TelephoneNumber(null);
        }
        return TEXT_PARSER.parse(input);
    }

    private static final TextParser<TelephoneNumber> TEXT_PARSER;

    static {
        TEXT_PARSER = new TelephoneNumberParser();
    }

    private static class TelephoneNumberParser implements TextParser<TelephoneNumber> {
        @Override
        public TelephoneNumber parse(CharSequence textInput) throws TextParserError {
            if (null == textInput) {
                throw new TextParserError("Unexpected null pointer detected at "+ this.getClass().getSimpleName());
            }
            String filtered = filterOutNoneDigitCharacters(textInput);
            if (!patternOfNumberIsValid(filtered)) {
                throw new TextParserError("电话号码格式不满足要求: " + textInput);
            }
            return new TelephoneNumber(filtered);
        }

        private final static Pattern NoneDigitCharacterFilterPattern = Pattern.compile("[^\\d]");

        private static String filterOutNoneDigitCharacters(CharSequence phoneNumber) {
            final Matcher matcher = NoneDigitCharacterFilterPattern.matcher(phoneNumber);
            return matcher.replaceAll("");
        }

        // TODO: 未来必要时可以引进更精确的手机号码匹配规则
        private final static Pattern TelephoneNumberPattern = Pattern.compile("^0[1-9]\\d{9,10}$");

        private static boolean patternOfNumberIsValid(CharSequence phoneNumber) {
            final Matcher matcher = TelephoneNumberPattern.matcher(phoneNumber);
            return matcher.matches();
        }
    }
}
